/* eslint-disable jsx-a11y/click-events-have-key-events */
import React from 'react';
import { TreeNode } from '~/types';

export interface TreeSelectProps {
  data: TreeNode[];
  onSelect: (node: TreeNode) => void;
  currentId?: string;
  className?: string;
  placeholder?: string;
  value?: string;
}

/**
 * <TreeSelect data={toTreeNode(treeSelectFetcher.data?.permissions ?? [])}
 *  value={(editPermissionInfo?.parent_id ?? "").toString()}
 *  currentId={(editPermissionInfo?.id ?? "").toString()}
 *  onSelect={handleTreeSelect}
 *  placeholder={t("pick_item")}
 *  className="w-full" />
 */
const TreeSelect = React.forwardRef(function TreeSelect(props: TreeSelectProps, ref: React.ForwardedRef<HTMLInputElement>) {
  const { data, onSelect, currentId, className, placeholder, value } = props;
  const [isOpen, setIsOpen] = React.useState(false);
  const [selectedNode, setSelectedNode] = React.useState<TreeNode | null>(null);
  const defaultNode = { id: '', name: '' };

  React.useEffect(() => {
    const findNodeWithChildren = (nodes: TreeNode[], value: string): TreeNode | null => {
      for (const node of nodes) {
        if (node.id === value) {
          return node;
        }
        if (node.children) {
          const foundNode = findNodeWithChildren(node.children, value);
          if (foundNode) {
            return foundNode;
          }
        }
      }
      return null;
    };

    if (value) {
      const node = findNodeWithChildren(data, value);
      if (node) {
        setSelectedNode(node);
      }
    } else {
      setSelectedNode({ id: '', name: '' });
    }
  }, [data, value])

  const toggleDropdown = () => {
    setIsOpen(!isOpen);
  };

  const handleSelectNode = (node: TreeNode, disabled: boolean) => {
    if (disabled) {
      return;
    }
    setSelectedNode(node);
    onSelect(node);
    setIsOpen(false);
  };

  const renderTree = (nodes: TreeNode[], depth: number = 0, disabled: boolean = false): JSX.Element[] => {
    return nodes.map((node) => {
      let isDisabled = false;
      if (disabled === true || (currentId && node.id === currentId)) {
        isDisabled = true;
      }
      return (
        <li key={node.id} className={isDisabled ? "disabled" : ""}>
          <span tabIndex={0} role="button" onClick={() => handleSelectNode(node, isDisabled)}>
            {node.name}
          </span>
          {node.children && node.children.length > 0 && (
            <ul>
              {renderTree(node.children, depth + 1, isDisabled)}
            </ul>
          )}
        </li>
      )
    });
  };

  return (
    <div className={`relative ${className}`}>
      <input
        type="text"
        className="select select-bordered w-full"
        onClick={toggleDropdown}
        placeholder={placeholder}
        value={selectedNode ? selectedNode.name : ""}
        ref={ref}
        readOnly
      />
      {isOpen && (
        <ul className="absolute z-10 w-full menu bg-base-200 rounded-box mt-1">
          <li key="0">
            <span tabIndex={0} role="button" className="opacity-50"
              onClick={() => handleSelectNode(defaultNode, false)}>
              {placeholder}
            </span>
          </li>
          {renderTree(data)}
        </ul>
      )}
    </div>
  );
})

export default TreeSelect;